package org.springframework.context.event;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * 简单实现的容器资源广播器
 * 实现了对于发布的事件的分发到对于的监听器
 */
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster{

    public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
        setBeanFactory(beanFactory);
    }


    /**
     * 对于发布的事件的分发到对于的监听器
     * @param event
     */
    @Override
    public void multicastEvent(ApplicationEvent event) {
        for (ApplicationListener<ApplicationEvent> applicationListener : applicationListeners) {
            //如果读取监听器支持这个事件 则调用执行方法
            if(supportsEvent(applicationListener, event)){
                applicationListener.onApplicationEvent(event);
            }
        }
    }

    /**
     * 判断监听器是否对该事件感兴趣
     *
     * @param applicationListener
     * @param event
     * @return
     */
    protected boolean supportsEvent(ApplicationListener<ApplicationEvent> applicationListener, ApplicationEvent event) {
        //获取监听器实现的接口
        Type type = applicationListener.getClass().getGenericInterfaces()[0];
        //通过接口里的事件泛型参数 来确定对读取事件类型是否感兴趣
        Type actualTypeArgument = ((ParameterizedType) type).getActualTypeArguments()[0];

        //获取接口里定义的事件类型
        String className = actualTypeArgument.getTypeName();
        Class<?> eventClass;
        try {
            eventClass = Class.forName(className);
        } catch (ClassNotFoundException e) {
            throw new BeansException("wrong event class name: " + className);
        }

        //判断接口里的事件类型是否和要处理的事件类型一致
        return eventClass.isAssignableFrom(event.getClass());
    }
}
